home *** CD-ROM | disk | FTP | other *** search
Wrap
Text File | 2003-12-17 | 71.3 KB | 1,470 lines
OPT PREPROCESS, OSVERSION=37 /* Program: Q-Device Version: V0.3 Author: Ian Chapman Description: A low-level SCSI query, command and diagnostic tool. LICENSE: Permission is granted to use this source code in whole or in part, providing that the author (Ian Chapman) is credited in your project in either the documentation, or the program itself. This applies to both free and commercial software. In the case of commerical software (including ShareWare), I am entitled to a free, fully functional copy of the software. NO WARRANTY EITHER EXPRESSED OR IMPLIED AS TO THE FITNESS OF THIS CODE FOR ANY PURPOSE. ALL USE IS ENTIRELY AND WHOLLY AT YOUR OWN RISK */ MODULE 'exec/ports', 'exec/io', 'exec/execbase', 'exec/lists', 'exec/nodes', 'amigalib/io', 'devices/scsidisk', 'muimaster', 'mui/betterstring_mcc', 'libraries/mui', 'libraries/gadtools', 'amigalib/boopsi', 'intuition/classusr', 'utility/tagitem', 'utility/hooks', 'tools/installhook', '*opcodes', '*params', '*headers' CONST BUFFSIZE=254 ENUM ID_INQUIRE=1, ID_EJECT, ID_INSERT, ID_LOCK, ID_UNLOCK, ID_CAPACITY, ID_TESTREADY, ID_READTOC, ID_POWERUP, ID_POWERDOWN, ID_PROBE, ID_ABOUT, ID_MUIABOUT, ID_ICONIFY, ID_MUISET, ID_DIAGNOSTIC, ID_DOUBLECLICK, ID_MODESENSE, ID_LOG_SUPPORT, ID_LOG_WRITE, ID_LOG_READ, ID_LOG_REVREAD, ID_LOG_VERIFY, ID_LOG_NMERRORS, ID_LOG_BUFFER, ID_LOG_EVENTS, ID_PREFS, ID_SAVEPREF, ID_USEPREF, ID_CANCELPREF ENUM NORMAL=0, ERR_MP=1, ERR_IOR, ERR_DEVICE, ERR_NOMUI, ERR_NOAPP ENUM OBID_DRIVER=1, OBID_UNIT, OBID_PROBEFROM, OBID_PROBETO OBJECT listentry -> Entries for the listview field value driver unit ENDOBJECT DEF app, mui_output_lst, mui_output_lv, mui_status_tb, mui_device_tb, mui_unit_tb, displayhook:hook, constructhook:hook, destructhook:hook, devicelist[50]:ARRAY OF LONG, execobject:PTR TO execbase, inquiry_type=TRUE, global_devtype=0 PROC main() HANDLE DEF signal, result, running=TRUE, driver[80]:STRING, unit[4]:STRING, probefrom[4]:STRING, probeto[4]:STRING, mui_probefrom_tb, mui_probeto_tb, mui_main_win, mui_prefs_win, mui_inquire_but, mui_eject_but, mui_insert_but, mui_lock_but, mui_unlock_but, mui_capacity_but, mui_testready_but, mui_readtoc_but, mui_powerup_but, mui_powerdown_but, mui_probe_but, mui_diagnostic_but, mui_modesense_but, mui_diagnostic_cyc, mui_prefsave_but, mui_prefuse_but, mui_prefcancel_but, mui_logsupport_but, mui_logwrite_but, mui_logread_but, mui_logrevread_but, mui_logverify_but, mui_lognmerrors_but, mui_logbuffer_but, mui_logevents_but, menu, diagflag=0, i grab_devices() menu:= [ NM_TITLE, 0, 'Project', 0, 0, 0, 0, NM_ITEM, 0, 'About...', '?', 0, 0, ID_ABOUT, NM_ITEM, 0, 'About MUI...', 0, 0, 0, ID_MUIABOUT, NM_ITEM, 0, NM_BARLABEL, 0, 0, 0, 0, NM_ITEM, 0, 'Iconify', 'I', 0, 0, ID_ICONIFY, NM_ITEM, 0, 'Quit', 'Q', 0, 0, MUIV_Application_ReturnID_Quit, NM_TITLE, 0, 'Query', 0, 0, 0, 0, NM_ITEM, 0, 'Probe', 0, 0, 0, ID_PROBE, NM_ITEM, 0, 'Full Inquiry', 0, 0, 0, ID_INQUIRE, NM_ITEM, 0, 'Capacity', 0, 0, 0, ID_CAPACITY, NM_ITEM, 0, 'Test Ready', 0, 0, 0, ID_TESTREADY, NM_ITEM, 0, 'Device Parameters', 0, 0, 0, ID_MODESENSE, NM_ITEM, 0, 'Read TOC', 0, 0, 0, ID_READTOC, NM_ITEM, 0, NM_BARLABEL, 0, 0, 0, 0, NM_ITEM, 0, 'Scan Firmware Logs', 0, 0, 0, ID_LOG_SUPPORT, NM_ITEM, 0, 'Write Errors', 0, 0, 0, ID_LOG_WRITE, NM_ITEM, 0, 'Read Errors', 0, 0, 0, ID_LOG_READ, NM_ITEM, 0, 'Rev. Read Errors', 0, 0, 0, ID_LOG_REVREAD, NM_ITEM, 0, 'Verify Errors', 0, 0, 0, ID_LOG_VERIFY, NM_ITEM, 0, 'Non Medium Errors', 0, 0, 0, ID_LOG_NMERRORS, NM_TITLE, 0, 'Control', 0, 0, 0, 0, NM_ITEM, 0, 'Power Up', 0, 0, 0, ID_POWERUP, NM_ITEM, 0, 'Power Down', 0, 0, 0, ID_POWERDOWN, NM_ITEM, 0, 'Lock', 0, 0, 0, ID_LOCK, NM_ITEM, 0, 'UnLock', 0, 0, 0, ID_UNLOCK, NM_ITEM, 0, 'Insert', 0, 0, 0, ID_INSERT, NM_ITEM, 0, 'Eject', 0, 0, 0, ID_EJECT, NM_TITLE, 0, 'Diagnostic', 0, 0, 0, 0, NM_ITEM, 0, 'Unit Self Test', 0, 0, 0, ID_DIAGNOSTIC, NM_TITLE, 0, 'Settings', 0, 0, 0, 0, NM_ITEM, 0, 'MUI Settings', 0, 0, 0, ID_MUISET, NM_ITEM, 0, 'Preferences', 'P', 0, 0, ID_PREFS, NM_ITEM, 0, NM_BARLABEL, 0, 0, 0, 0, NM_ITEM, 0, 'Save Preferences', 0, 0, 0, ID_SAVEPREF, NM_END, 0, NIL, 0, 0, 0, 0]:newmenu IF (muimasterbase:=OpenLibrary('muimaster.library', 19))=NIL THEN Raise(ERR_NOMUI) installhook(displayhook, {disp}) installhook(constructhook, {construct}) installhook(destructhook, {destruct}) mui_output_lv:=ListviewObject, MUIA_Listview_Input, MUI_TRUE, MUIA_CycleChain, 1, MUIA_Listview_List, mui_output_lst:=ListObject, ReadListFrame, MUIA_List_Title, MUI_TRUE, MUIA_List_Format, 'BAR,', MUIA_List_DisplayHook, displayhook, MUIA_List_ConstructHook, constructhook, ->MUIV_List_ConstructHook_String, MUIA_List_DestructHook, destructhook, ->MUIV_List_DestructHook_String, MUIA_ShortHelp, 'Information and diagnostic output', End, -> ReadListFrame End ->Listviewobject mui_inquire_but:=make_button('Full Inquiry', 'Display full inquiry information') mui_eject_but:=make_button('Eject', 'Attempt to eject media') mui_insert_but:=make_button('Insert', 'Attempt to insert media') mui_lock_but:=make_button('Lock', 'Prevent media from being removed') mui_unlock_but:=make_button('UnLock', 'Allow media to be removed') mui_capacity_but:=make_button('Capacity', 'Show device capacity') mui_testready_but:=make_button('Test Ready', 'Test if unit is ready') mui_readtoc_but:=make_button('Read TOC', 'Show CD Table of Contents') mui_powerup_but:=make_button('Power Up', 'Attempt to spin-up the device') mui_powerdown_but:=make_button('Power Down', 'Attempt to spin-down the device') mui_probe_but:=make_button('Probe', 'Probe driver for attached devices') mui_diagnostic_but:=make_button('Start Self Test', 'Instruct the device to perform a self test') mui_modesense_but:=make_button('Device Parameters', 'Return information about the device\as parameters and specs') mui_logsupport_but:=make_button('Scan Firmware Logs', 'Lists the known log types in the device\as firmware') mui_logwrite_but:=make_button('Write Errors', 'Show the Write Error log for the device') mui_logread_but:=make_button('Read Errors', 'Show the Read Error log for the device') mui_logrevread_but:=make_button('Rev. Read Errors', 'Show the Reverse Read Error log for the device') mui_logverify_but:=make_button('Verify Errors', 'Show the Verify Error log for the device') mui_lognmerrors_but:=make_button('Non Medium Errors', 'Show the log of errors not related to media') mui_logbuffer_but:=make_button('Buffer', 'Show the log of buffer over-runs and under-runs') mui_logevents_but:=make_button('Events', 'Show the log of events') mui_prefsave_but:=make_button('Save', 'Save preferences') mui_prefuse_but:=make_button('Use', 'Use preferences, changes are lost after reboot') mui_prefcancel_but:=make_button('Cancel', 'Discard any changes') mui_diagnostic_cyc:=make_keycycle(['Simple 1', 'Simple 2', 'Deep 1', 'Deep 2', NIL], "t", 'Choose diagnostic test') mui_device_tb:=BetterStringObject, StringFrame, MUIA_String_AdvanceOnCR, MUI_TRUE, MUIA_String_Contents, driver, MUIA_ShortHelp, 'Device driver to use', MUIA_CycleChain, 1, MUIA_ObjectID, OBID_DRIVER, End mui_unit_tb:=BetterStringObject, StringFrame, MUIA_String_AdvanceOnCR, MUI_TRUE, MUIA_String_Contents, unit, MUIA_ShortHelp, 'Device unit number', MUIA_String_Accept, '0123456789', MUIA_String_MaxLen, 4, MUIA_CycleChain, 1, MUIA_ObjectID, OBID_UNIT, End mui_status_tb:=TextObject, TextFrame, MUIA_String_Contents, 'Ready', MUIA_ShortHelp, 'SCSI/IDE target condition', End mui_probefrom_tb:=BetterStringObject, StringFrame, MUIA_String_AdvanceOnCR, MUI_TRUE, MUIA_String_Contents, probefrom, MUIA_ShortHelp, 'Probing devices starts at this unit', MUIA_String_Accept, '0123456789', MUIA_String_MaxLen, 4, MUIA_CycleChain, 1, MUIA_ObjectID, OBID_PROBEFROM, End mui_probeto_tb:=BetterStringObject, StringFrame, MUIA_String_AdvanceOnCR, MUI_TRUE, MUIA_String_Contents, probeto, MUIA_ShortHelp, 'Probing devices ends at this unit', MUIA_String_Accept, '0123456789', MUIA_String_MaxLen, 4, MUIA_CycleChain, 1, MUIA_ObjectID, OBID_PROBETO, End app:=ApplicationObject, MUIA_Application_Title , 'Q-Device!', MUIA_Application_Version , '$VER: Q-Device! v0.3', MUIA_Application_Copyright , 'Written By Ian Chapman (2003)', MUIA_Application_Author , 'Ian Chapman', MUIA_Application_Description, 'IDE/SCSI device query tool', MUIA_Application_Base , 'QDEVICE', MUIA_Application_SingleTask , FALSE, MUIA_Application_Menustrip , Mui_MakeObjectA(MUIO_MenustripNM,[menu,0]), MUIA_Application_HelpFile , 'Q-Device!.guide', SubWindow, mui_main_win:=WindowObject, MUIA_Window_Title , 'Q-Device! V0.3 by Ian Chapman', MUIA_Window_ID , "QDEV", MUIA_Window_Activate , MUI_TRUE, WindowContents, VGroup, Child, HGroup, Child, Label('Driver:'), Child, PoplistObject, MUIA_Popstring_String, mui_device_tb, MUIA_Popstring_Button, PopButton( MUII_PopUp ), MUIA_Poplist_Array, devicelist, End, Child, Label('Unit:'), Child, PoplistObject, MUIA_Popstring_String, mui_unit_tb, MUIA_Popstring_Button, PopButton( MUII_PopUp ), MUIA_Poplist_Array, ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', NIL], End, End, ->HGroup Child, HGroup, Child, Label('Target Status:'), Child, mui_status_tb, End, -> HGroup Child, RegisterGroup(['Query', 'Control', 'Diagnostic', NIL]), Child, VGroup, Child, ColGroup(3), GroupFrame, Child, mui_probe_but, Child, mui_inquire_but, Child, mui_capacity_but, Child, mui_testready_but, Child, mui_modesense_but, Child, mui_readtoc_but, End, -> ColGroup Child, VSpace(10), Child, ColGroup(3), GroupFrameT('Firmware Logs'), Child, mui_logsupport_but, Child, mui_logwrite_but, Child, mui_logread_but, Child, mui_logrevread_but, Child, mui_logverify_but, Child, mui_lognmerrors_but, ->Child, mui_logbuffer_but, ->Child, mui_logevents_but, ->Child, HSpace(0), End, -> ColGroup End, -> VGroup Child, ColGroup(2), Child, mui_powerup_but, Child, mui_powerdown_but, Child, mui_lock_but, Child, mui_unlock_but, Child, mui_insert_but, Child, mui_eject_but, End, -> Colgroup Child, ColGroup(2), GroupFrameT('Diagnostic Tests'), Child, HGroup, Child, Label('_Test Type:'), Child, mui_diagnostic_cyc, End, -> HGroup Child, mui_diagnostic_but, End, -> ColGroup End, -> Register, Child, BalanceObject, End, Child, mui_output_lv, End, ->VGroup End, -> WindowObject SubWindow, mui_prefs_win:=WindowObject, MUIA_Window_Title , 'Preferences', MUIA_Window_ID , "PREF", MUIA_Window_Activate , MUI_TRUE, MUIA_HelpNode , 'Preferences Window', WindowContents, VGroup, Child, ColGroup(2), Child, Label('Probe Units From:'), Child, HGroup, Child, mui_probefrom_tb, Child, Label('To:'), Child, mui_probeto_tb, End, -> HGroup End, -> ColGroup Child, BalanceObject, End, Child, HGroup, Child, mui_prefsave_but, Child, mui_prefuse_but, Child, mui_prefcancel_but, End, -> HGroup End, -> VGroup End, -> Window End -> Application IF (app=NIL) THEN Raise(ERR_NOAPP) doMethodA(mui_inquire_but, [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_INQUIRE]) doMethodA(mui_eject_but, [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_EJECT]) doMethodA(mui_insert_but, [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_INSERT]) doMethodA(mui_lock_but, [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_LOCK]) doMethodA(mui_unlock_but, [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_UNLOCK]) doMethodA(mui_capacity_but, [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_CAPACITY]) doMethodA(mui_testready_but, [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_TESTREADY]) doMethodA(mui_readtoc_but, [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_READTOC]) doMethodA(mui_powerup_but, [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_POWERUP]) doMethodA(mui_powerdown_but, [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_POWERDOWN]) doMethodA(mui_probe_but, [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_PROBE]) doMethodA(mui_diagnostic_but, [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_DIAGNOSTIC]) doMethodA(mui_modesense_but, [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_MODESENSE]) doMethodA(mui_logsupport_but, [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_LOG_SUPPORT]) doMethodA(mui_logwrite_but, [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_LOG_WRITE]) doMethodA(mui_logread_but, [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_LOG_READ]) doMethodA(mui_logrevread_but, [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_LOG_REVREAD]) doMethodA(mui_logverify_but, [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_LOG_VERIFY]) doMethodA(mui_lognmerrors_but, [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_LOG_NMERRORS]) doMethodA(mui_logbuffer_but, [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_LOG_BUFFER]) doMethodA(mui_logevents_but, [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_LOG_EVENTS]) doMethodA(mui_prefsave_but, [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_SAVEPREF]) doMethodA(mui_prefuse_but, [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_USEPREF]) doMethodA(mui_prefcancel_but, [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_CANCELPREF]) doMethodA(mui_diagnostic_cyc, [MUIM_Notify, MUIA_Cycle_Active, MUIV_EveryTime, mui_diagnostic_cyc, 3, MUIM_WriteLong, MUIV_TriggerValue, {diagflag}]) doMethodA(mui_device_tb, [MUIM_Notify, MUIA_String_Contents, MUIV_EveryTime, mui_device_tb, 3, MUIM_WriteString, MUIV_TriggerValue, driver]) doMethodA(mui_unit_tb, [MUIM_Notify, MUIA_String_Contents, MUIV_EveryTime, mui_unit_tb, 3, MUIM_WriteString, MUIV_TriggerValue, unit]) doMethodA(mui_probefrom_tb, [MUIM_Notify, MUIA_String_Contents, MUIV_EveryTime, mui_probefrom_tb, 3, MUIM_WriteString, MUIV_TriggerValue, probefrom]) doMethodA(mui_probeto_tb, [MUIM_Notify, MUIA_String_Contents, MUIV_EveryTime, mui_probeto_tb, 3, MUIM_WriteString, MUIV_TriggerValue, probeto]) doMethodA(mui_main_win, [MUIM_Notify, MUIA_Window_CloseRequest, MUI_TRUE, app, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit]) doMethodA(mui_prefs_win, [MUIM_Notify, MUIA_Window_CloseRequest, MUI_TRUE, app, 2, MUIM_Application_ReturnID, ID_CANCELPREF]) doMethodA(mui_output_lv, [MUIM_Notify, MUIA_Listview_DoubleClick, MUI_TRUE, app, 2, MUIM_Application_ReturnID, ID_DOUBLECLICK]) set(mui_status_tb, MUIA_Text_Contents, 'Ready') SetAttrsA(mui_main_win, [MUIA_Window_ActiveObject, mui_unit_tb, MUIA_Window_Open, MUI_TRUE, TAG_DONE]) doMethodA(app, [MUIM_Application_Load, MUIV_Application_Load_ENV]) IF (StrCmp(unit, '', ALL) = TRUE) StrCopy(unit, '0') set(mui_unit_tb, MUIA_String_Contents, '0') ENDIF IF (StrCmp(driver, '', ALL) = TRUE) StrCopy(driver, 'gvpscsi.device') set(mui_device_tb, MUIA_String_Contents, 'gvpscsi.device') ENDIF IF (StrCmp(probefrom, '', ALL) = TRUE) StrCopy(probefrom, '0') set(mui_probefrom_tb, MUIA_String_Contents, '0') ENDIF IF (StrCmp(probeto, '', ALL) = TRUE) StrCopy(probeto, '15') set(mui_probeto_tb, MUIA_String_Contents, '15') ENDIF WHILE running result:=doMethodA(app, [MUIM_Application_Input,{signal}]) SELECT result CASE MUIV_Application_ReturnID_Quit running:=FALSE CASE ID_SAVEPREF doMethodA(app, [MUIM_Application_Save, MUIV_Application_Save_ENV]) doMethodA(app, [MUIM_Application_Save, MUIV_Application_Save_ENVARC]) set(mui_prefs_win, MUIA_Window_Open, FALSE) CASE ID_USEPREF doMethodA(app, [MUIM_Application_Save, MUIV_Application_Save_ENV]) set(mui_prefs_win, MUIA_Window_Open, FALSE) CASE ID_CANCELPREF doMethodA(app, [MUIM_Application_Load, MUIV_Application_Load_ENV]) set(mui_prefs_win, MUIA_Window_Open, FALSE) CASE ID_PREFS set(mui_prefs_win, MUIA_Window_Open, MUI_TRUE) CASE ID_INQUIRE doMethodA(mui_output_lst, [MUIM_List_Clear]) inquiry_type:=TRUE query(driver, Val(unit), [SCSI_INQUIRY, 0, 0, 0, BUFFSIZE, 0]:cdb6, SIZEOF cdb6) CASE ID_EJECT doMethodA(mui_output_lst, [MUIM_List_Clear]) query(driver, Val(unit), [SCSI_CD_START_STOP_UNIT, 0, 0, 0, P_EJECT, 0]:cdb6, SIZEOF cdb6) CASE ID_INSERT doMethodA(mui_output_lst, [MUIM_List_Clear]) query(driver, Val(unit), [SCSI_CD_START_STOP_UNIT, 0, 0, 0, P_INSERT, 0]:cdb6, SIZEOF cdb6) CASE ID_POWERUP doMethodA(mui_output_lst, [MUIM_List_Clear]) query(driver, Val(unit), [SCSI_DA_START_STOP_UNIT, 0, 0, 0, P_START, 0]:cdb6, SIZEOF cdb6) CASE ID_POWERDOWN doMethodA(mui_output_lst, [MUIM_List_Clear]) query(driver, Val(unit), [SCSI_DA_START_STOP_UNIT, 0, 0, 0, P_STOP, 0]:cdb6, SIZEOF cdb6) CASE ID_LOCK doMethodA(mui_output_lst, [MUIM_List_Clear]) query(driver, Val(unit), [SCSI_CD_PREVENT_ALLOW_MEDIUM_REMOVAL, 0, 0, 0, P_LOCK, 0]:cdb6, SIZEOF cdb6) CASE ID_UNLOCK doMethodA(mui_output_lst, [MUIM_List_Clear]) query(driver, Val(unit), [SCSI_CD_PREVENT_ALLOW_MEDIUM_REMOVAL, 0, 0, 0, P_UNLOCK, 0]:cdb6, SIZEOF cdb6) CASE ID_CAPACITY doMethodA(mui_output_lst, [MUIM_List_Clear]) query(driver, Val(unit), [SCSI_DA_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0]:cdb10, SIZEOF cdb10) CASE ID_TESTREADY doMethodA(mui_output_lst, [MUIM_List_Clear]) query(driver, Val(unit), [SCSI_TEST_UNIT_READY, 0, 0, 0, 0, 0]:cdb6, SIZEOF cdb6) CASE ID_READTOC doMethodA(mui_output_lst, [MUIM_List_Clear]) query(driver, Val(unit), [SCSI_CD_READ_TOC, 0, 0, 0, 0, 0, 1, 0, BUFFSIZE, 0]:cdb10, SIZEOF cdb10) CASE ID_PROBE doMethodA(mui_output_lst, [MUIM_List_Clear]) inquiry_type:=MUI_TRUE IF Val(probefrom) > Val(probeto) FOR i:=Val(probefrom) TO Val(probeto) STEP -1 DO query(driver, i, [SCSI_INQUIRY, 0, 0, 0, BUFFSIZE, 0]:cdb6, SIZEOF cdb6) ELSE FOR i:=Val(probefrom) TO Val(probeto) DO query(driver, i, [SCSI_INQUIRY, 0, 0, 0, BUFFSIZE, 0]:cdb6, SIZEOF cdb6) ENDIF CASE ID_DIAGNOSTIC doMethodA(mui_output_lst, [MUIM_List_Clear]) SELECT diagflag CASE 0 query(driver, Val(unit), [SCSI_SEND_DIAGNOSTIC, P_DIAG_SIMPLE1, 0, 0, 0, 0]:cdb6, SIZEOF cdb6) CASE 1 query(driver, Val(unit), [SCSI_SEND_DIAGNOSTIC, P_DIAG_SIMPLE2, 0, 0, 0, 0]:cdb6, SIZEOF cdb6) CASE 2 IF Mui_RequestA(app, mui_main_win, 0, 'Warning!', '_Proceed|*_Cancel', 'A deep test may require the device to take itself offline temporarily\nor make temporary changes to the medium. It is highly recommended\nyou make sure nothing else is accessing the device before performing\nthis test.', NIL)<>0 query(driver, Val(unit), [SCSI_SEND_DIAGNOSTIC, P_DIAG_COMPLEX1, 0, 0, 0, 0]:cdb6, SIZEOF cdb6) ENDIF CASE 3 IF Mui_RequestA(app, mui_main_win, 0, 'Warning!', '_Proceed|*_Cancel', 'A deep test may require the device to take itself offline temporarily\nor make temporary changes to the medium. It is highly recommended\nyou make sure nothing else is accessing the device before performing\nthis test.', NIL)<>0 query(driver, Val(unit), [SCSI_SEND_DIAGNOSTIC, P_DIAG_COMPLEX2, 0, 0, 0, 0]:cdb6, SIZEOF cdb6) ENDIF ENDSELECT CASE ID_MODESENSE doMethodA(mui_output_lst, [MUIM_List_Clear]) inquiry_type:=FALSE IF query(driver, Val(unit), [SCSI_INQUIRY, 0, 0, 0, BUFFSIZE, 0]:cdb6, SIZEOF cdb6)=0 query(driver, Val(unit), [SCSI_MODE_SENSE_6, 0, P_ALLPAGES, 0, BUFFSIZE, 0]:cdb6, SIZEOF cdb6) ENDIF CASE ID_LOG_SUPPORT doMethodA(mui_output_lst, [MUIM_List_Clear]) query(driver, Val(unit), [SCSI_LOG_SENSE, 0, 0, 0, 0, 0, 0, BUFFSIZE, 0]:cdb10, SIZEOF cdb10) CASE ID_LOG_WRITE doMethodA(mui_output_lst, [MUIM_List_Clear]) query(driver, Val(unit), [SCSI_LOG_SENSE, 0, P_LOG_WRITE, 0, 0, 0, 0, BUFFSIZE, 0]:cdb10, SIZEOF cdb10) CASE ID_LOG_READ doMethodA(mui_output_lst, [MUIM_List_Clear]) query(driver, Val(unit), [SCSI_LOG_SENSE, 0, P_LOG_READ, 0, 0, 0, 0, BUFFSIZE, 0]:cdb10, SIZEOF cdb10) CASE ID_LOG_REVREAD doMethodA(mui_output_lst, [MUIM_List_Clear]) query(driver, Val(unit), [SCSI_LOG_SENSE, 0, P_LOG_REVREAD, 0, 0, 0, 0, BUFFSIZE, 0]:cdb10, SIZEOF cdb10) CASE ID_LOG_VERIFY doMethodA(mui_output_lst, [MUIM_List_Clear]) query(driver, Val(unit), [SCSI_LOG_SENSE, 0, P_LOG_VERIFY, 0, 0, 0, 0, BUFFSIZE, 0]:cdb10, SIZEOF cdb10) CASE ID_LOG_NMERRORS doMethodA(mui_output_lst, [MUIM_List_Clear]) query(driver, Val(unit), [SCSI_LOG_SENSE, 0, P_LOG_NMERRORS, 0, 0, 0, 0, BUFFSIZE, 0]:cdb10, SIZEOF cdb10) CASE ID_LOG_BUFFER doMethodA(mui_output_lst, [MUIM_List_Clear]) query(driver, Val(unit), [SCSI_LOG_SENSE, 0, P_LOG_BUFFER, 0, 0, 0, 0, BUFFSIZE, 0]:cdb10, SIZEOF cdb10) CASE ID_LOG_EVENTS doMethodA(mui_output_lst, [MUIM_List_Clear]) query(driver, Val(unit), [SCSI_LOG_SENSE, 0, P_LOG_EVENTS, 0, 0, 0, 0, BUFFSIZE, 0]:cdb10, SIZEOF cdb10) CASE ID_ABOUT Mui_RequestA(app, mui_main_win, 0, 'About Q-Device!', '*_OK', '\ecQ-Device! by Ian Chapman (2003)\nVersion 0.3\n\nA low-level SCSI/IDE query, control and diagnostic tool\n\n\ebUse of this software is entirely at YOUR OWN risk!\en', NIL) CASE ID_MUIABOUT doMethodA(app, [MUIM_Application_AboutMUI, mui_main_win]) CASE ID_MUISET doMethodA(app, [MUIM_Application_OpenConfigWindow, 0]) CASE ID_ICONIFY set(app, MUIA_Application_Iconified, MUI_TRUE) CASE ID_DOUBLECLICK inquiry_type:=TRUE click_inquiry() ENDSELECT IF (running AND signal) THEN Wait(signal) ENDWHILE EXCEPT DO IF (app) THEN Mui_DisposeObject(app) IF (muimasterbase) THEN CloseLibrary(muimasterbase) SELECT exception CASE NORMAL ->Normal Exit CASE ERR_NOMUI PrintF('Unable to open muimaster.library V19+\n') CASE ERR_NOAPP PrintF('Unable to create application\n') DEFAULT PrintF('Unknown exception of type (\d)\n', exception) ENDSELECT ENDPROC /* ** This procedure takes a SCSI command definition, then passes the results to ** a handler procedure, depending on the SCSI command sent. */ PROC query(device:PTR TO CHAR, unit, cmd:PTR TO cdb12, size) HANDLE DEF myport=NIL:PTR TO mp, ioreq=NIL:PTR TO iostd, buffer=NIL, scsiio:scsicmd, command, error=-1, status IF (myport:=CreateMsgPort())=NIL THEN Raise(ERR_MP) IF (ioreq:=createStdIO(myport))=NIL THEN Raise(ERR_IOR) IF (error:=OpenDevice(device, unit, ioreq, 0)) <> NIL THEN Raise(ERR_DEVICE) buffer:=New(BUFFSIZE) command:=cmd.opcode scsiio.data:=buffer scsiio.length:=BUFFSIZE scsiio.command:=cmd scsiio.cmdlength:=size scsiio.flags:=SCSIF_READ -> OR SCSIF_AUTOSENSE scsiio.senseactual:=0 ioreq.command:=HD_SCSICMD ioreq.data:=scsiio ioreq.length:=SIZEOF scsicmd DoIO(ioreq) status:=ioreq.error SELECT $FF OF (scsiio.status AND M_STATUS) CASE 0 IF command <> SCSI_REQUEST_SENSE THEN set(mui_status_tb, MUIA_Text_Contents, 'Target Response: GOOD') SELECT command CASE SCSI_CD_READ_TOC process_toc(buffer) CASE SCSI_TEST_UNIT_READY outlist_d('Unit Ready', device, unit) CASE SCSI_INQUIRY process_inquiry(device, unit, buffer) CASE SCSI_DA_READ_CAPACITY process_capacity(buffer) CASE SCSI_CD_START_STOP_UNIT IF cmd.param4=P_EJECT outlist_d('Sent eject command', device, unit) ELSEIF cmd.param4=P_INSERT outlist_d('Sent insert command', device, unit) ELSEIF cmd.param4=P_START outlist_d('Sent power up command', device, unit) ELSEIF cmd.param4=P_STOP outlist_d('Sent power down command', device, unit) ENDIF CASE SCSI_CD_PREVENT_ALLOW_MEDIUM_REMOVAL IF cmd.param4=P_LOCK outlist_d('Sent lock command', device, unit) ELSE outlist_d('Sent unlock command', device, unit) ENDIF CASE SCSI_REQUEST_SENSE process_sense(buffer) CASE SCSI_MODE_SENSE_6 process_modesense(buffer) CASE SCSI_LOG_SENSE SELECT $3F OF Char(buffer) CASE $0 outlist('\ebLog Type:\en', 'List of supported log types') process_log_support(buffer) CASE $1 outlist('\ebLog Type:\en', 'Buffer over/under runs') process_log_buffer(buffer) CASE $2 outlist('\ebLog Type:\en', 'Write Errors') process_log_errors(buffer) CASE $3 outlist('\ebLog Type:\en', 'Read Errors') process_log_errors(buffer) CASE $4 outlist('\ebLog Type:\en', 'Reverse Read Errors') process_log_errors(buffer) CASE $5 outlist('\ebLog Type:\en', 'Verify Errors') process_log_errors(buffer) CASE $6 outlist('\ebLog Type:\en', 'Errors not related to media') process_log_nmerrors(buffer) CASE $7 outlist('\ebLog Type:\en', 'Last number of error events') process_log_events(buffer) DEFAULT outlist('\ebLog Type:\en', 'Vendor Specific Log') ENDSELECT CASE SCSI_SEND_DIAGNOSTIC outlist_d('Self Test Passed', device, unit) ENDSELECT CASE 2 IF command <> SCSI_REQUEST_SENSE -> Hopefully avoids recursive loops with bad devices/drivers which don't support request sense. set(mui_status_tb, MUIA_Text_Contents, 'Target Response: CHECK_CONDITION') outlist('\ebWarning:\en', 'Command generated an error response (see below)') query(device, unit, [SCSI_REQUEST_SENSE, 0, 0, 0, BUFFSIZE, 0]:cdb6, SIZEOF cdb6) ENDIF CASE 4 set(mui_status_tb, MUIA_Text_Contents, 'Target Response: CONDITION_MET') CASE 8 set(mui_status_tb, MUIA_Text_Contents, 'Target Response: BUSY') CASE 16 set(mui_status_tb, MUIA_Text_Contents, 'Target Response: INTERMEDIATE') CASE 20 set(mui_status_tb, MUIA_Text_Contents, 'Target Response: INTERMEDIATE_CONDITION_MET') CASE 24 set(mui_status_tb, MUIA_Text_Contents, 'Target Response: RESERVATION_CONFLICT') CASE 34 set(mui_status_tb, MUIA_Text_Contents, 'Target Response: COMMAND_TERMINATED') CASE 72 set(mui_status_tb, MUIA_Text_Contents, 'Target Response: QUEUE_FULL') DEFAULT set(mui_status_tb, MUIA_Text_Contents, 'Target Response: UNKNOWN') ENDSELECT SELECT status CASE 0 ->Normal Return CASE HFERR_SELFUNIT outlist_d('<self issuing command error>', device, unit) CASE HFERR_DMA outlist_d('<DMA Failure>', device, unit) CASE HFERR_PHASE outlist_d('<illegal scsi phase>', device, unit) CASE HFERR_PARITY outlist_d('<parity error>', device, unit) CASE HFERR_SELTIMEOUT outlist_d('<device timed out>', device, unit) ENDSELECT EXCEPT DO IF error=NIL IF CheckIO(ioreq)<>NIL AbortIO(ioreq) WaitIO(ioreq) ENDIF ENDIF CloseDevice(ioreq) IF ioreq <> NIL THEN deleteStdIO(ioreq) IF myport <> NIL THEN DeleteMsgPort(myport) SELECT exception CASE ERR_MP outlist('\ebError:\en', 'Unable to create message port') CASE ERR_IOR outlist('\ebError:\en', 'Unable to create IORequest') CASE ERR_DEVICE outlist_d('<no device>', device, unit) ENDSELECT ENDPROC exception /* ** This procedure handles the data returned from an inquiry command. It has ** three modes of operation depending on the value of the 'inquiry_type' global ** variable. These are full (for full inquiry), minimum (for probes) and silent ** for passing the device type to the mode sense handler */ PROC process_inquiry(device:PTR TO CHAR, unit, reply:PTR TO inquiry) DEF devtypestr[40]:STRING, buildstr[99]:STRING, vendor[8]:STRING, product[16]:STRING, revision[4]:STRING, devtype=0 devtype:=(reply.peripheral AND M_DEVTYPE) global_devtype:=devtype SELECT devtype CASE DEV_DIRECT StrCopy(devtypestr, 'DIRECT ACCESS (eg Disk)') CASE DEV_SEQUENTIAL StrCopy(devtypestr, 'SEQUENTIAL ACCESS (eg Tape)') CASE DEV_PRINTER StrCopy(devtypestr, 'PRINTER') CASE DEV_PROCESSOR StrCopy(devtypestr, 'PROCESSOR') CASE DEV_WRITEONCE StrCopy(devtypestr, 'WRITE-ONCE (eg Optical Disc)') CASE DEV_CDROM StrCopy(devtypestr, 'CD-ROM') CASE DEV_SCANNER StrCopy(devtypestr, 'SCANNER') CASE DEV_OPTICAL StrCopy(devtypestr, 'OPTICAL MEMORY') CASE DEV_CHANGER StrCopy(devtypestr, 'MEDIUM CHANGER (eg Jukebox)') CASE DEV_COMMS StrCopy(devtypestr, 'COMMUNICATIONS') DEFAULT StrCopy(devtypestr, 'UNKNOWN') ENDSELECT MidStr(vendor, reply, 8, 7) MidStr(product, reply, 16, 16) MidStr(revision, reply, 32, 4) IF inquiry_type=MUI_TRUE StringF(buildstr, '\s \s \s :\s', vendor, product, revision, devtypestr) outlist_d(buildstr, device, unit) ELSEIF inquiry_type=TRUE outlist('\ebDriver:\en', device) outlist_i('\ebUnit:\en', unit, NIL) outlist('\ebVendor:\en', vendor) outlist('\ebProduct:\en', product) outlist('\ebRevision:\en', revision) outlist('\ebType:\en', devtypestr) IF (reply.rmb AND M_RMB) = 128 THEN outlist('\ebRemovable Media:\en:', 'Yes') ELSE outlist('\ebRemovable Media:\en:', 'No') outlist_i('\ebVendor Type Modifier:\en', (reply.rmb AND M_VENDORTYPE), NIL) outlist_i('\ebISO Version:\en', (reply.versions AND M_ISOVER), NIL) outlist_i('\ebECMA Version:\en', (reply.versions AND M_ECMAVER), NIL ) outlist_i('\ebANSI Version:\en', (reply.versions AND M_ANSIVER), ' (SCSI Version)') IF (reply.aenc AND M_AENC) = 128 THEN outlist('\ebAENC Support:\en', 'Yes') ELSE outlist('\ebAENC Support:\en', 'No') IF (reply.aenc AND M_TRMIOP) = 64 THEN outlist('\ebTrmIOP Support:\en', 'Yes') ELSE outlist('\ebTrmIOP Support:\en', 'No') IF (reply.width AND M_RELADR) = 128 THEN outlist('\ebRelative Addressing:\en', 'Yes') ELSE outlist('\ebRelative Addressing:\en', 'No') IF (reply.width AND M_WIDTH32) = 64 THEN outlist('\eb32bit Support:\en', 'Yes') ELSE outlist('\eb32bit Support:\en', 'No') IF (reply.width AND M_WIDTH16) = 32 THEN outlist('\eb16bit Support\en', 'Yes') ELSE outlist('\eb16bit Support\en', 'No') outlist('\eb8bit Support\en', 'Yes') IF (reply.width AND M_SYNC) = 16 THEN outlist('\ebSynchronous Support:\en', 'Yes') ELSE outlist('\ebSynchronous Support:\en', 'No') IF (reply.width AND M_LINKED) = 8 THEN outlist('\ebLinked Support:\en', 'Yes') ELSE outlist('\ebLinked Support:\en', 'No') IF (reply.width AND M_CMDQUE) = 2 THEN outlist('\ebCommand Queuing Support:\en', 'Yes') ELSE outlist('\ebCommand Queuing Support:\en', 'No') IF (reply.width AND M_RESET) = 1 THEN outlist('\ebSupported Reset Type:\en', 'Soft') ELSE outlist('\ebSupported Reset Type:\en', 'Hard') ENDIF ENDPROC /* ** This procedure handles the data returned from a capacity query */ PROC process_capacity(reply:PTR TO capacity) DEF buildstr[99]:STRING, tcap, vcap tcap:=Div(Mul(Div(reply.blocks, 1024), reply.bsize), 1024) vcap:=Div(Mul(Div(reply.blocks, 1000), reply.bsize), 1000) outlist_i('\ebBlocks:\en', reply.blocks, NIL) outlist_i('\ebBlock Size:\en', reply.bsize, ' bytes') IF tcap<1024 THEN StringF(buildstr, '~ \dMB', tcap) ELSE StringF(buildstr, '~ \d.\d GB (\d MB)', Div(tcap, 1024), (Mod(tcap, 1024)/100), tcap) outlist('\ebTrue Capacity:\en', buildstr) IF vcap<1000 THEN StringF(buildstr, '~ \dmb', vcap) ELSE StringF(buildstr, '~ \d.\d gb (\d mb)', Div(vcap, 1000), (Mod(vcap, 1000)/100), vcap) outlist('\ebVendor Capacity:\en', buildstr) ENDPROC /* ** This procedure handles the data returned from a Read Table of Contents ** query */ PROC process_toc(reply:PTR TO toc) DEF track:PTR TO toc_d, i outlist_i('\ebStarting Track:\eb', reply.firsttrack, NIL) outlist_i('\ebLast Track:\eb', reply.lasttrack, NIL) track:=reply + SIZEOF toc FOR i:=reply.firsttrack TO reply.lasttrack outlist(' ', ' ') outlist_i('\ebTrack Number:\en', track.track, NIL) IF (track.adr_ctrl AND M_TRACKTYPE)=0 outlist('\ebType:\en', 'AUDIO') IF (track.adr_ctrl AND M_CHANNELS)=0 THEN outlist('\ebAudio Channels:\en', '2') ELSE outlist('\ebAudio Channels:\en', '4') IF (track.adr_ctrl AND M_EMPHASIS)=0 THEN outlist('\ebEmphasis:\en', 'Audio IS pre-emphasised') ELSE outlist('\ebEmphasis:\en', 'Audio NOT pre-emphasised') ELSE outlist('\ebTrack Type:\en', 'DATA') ENDIF IF (track.adr_ctrl AND M_COPYRIGHT)=0 THEN outlist('\ebCopyright:\en', 'Digital Copy Prohibited') ELSE outlist('\ebCopyright:\en', 'Digital Copy Permitted') track:=track + SIZEOF toc_d ENDFOR ENDPROC /* ** This procedure handles the data returned from a request sense key query */ PROC process_sense(reply:PTR TO r_sense) DEF key ->cmdinfo:PTR TO r_sense_d, key key:=(reply.sensekey AND M_SENSEKEY) ->cmdinfo:=reply + SIZEOF r_sense SELECT key CASE $0 outlist_h('\ebSense Key:\en', key, ' : No Specific Sense Key Info Available') CASE $1 outlist_h('\ebSense Key:\en', key, ' : Command recovered successfully from error') CASE $2 outlist_h('\ebSense Key:\en', key, ' : Unit is not ready for commands') CASE $3 outlist_h('\ebSense Key:\en', key, ' : Medium Error. The medium may contain errors or defects.') CASE $4 outlist_h('\ebSense Key:\en', key, ' : DEVICE REPORTED HARDWARE FAILURE!!!') CASE $5 outlist_h('\ebSense Key:\en', key, ' : This device does not support that command') CASE $6 outlist_h('\ebSense Key:\en', key, ' : Unit Attention, possible media change in progress') CASE $7 outlist_h('\ebSense Key:\en', key, ' : Medium is write-protected') CASE $8 outlist_h('\ebSense Key:\en', key, ' : Attempt to read unformatted medium') CASE $9 outlist_h('\ebSense Key:\en', key, ' : Vendor specific sense key') CASE $A outlist_h('\ebSense Key:\en', key, ' : Copy/Compare command aborted due to read/write error') CASE $B outlist_h('\ebSense Key:\en', key, ' : Command was aborted by the device') CASE $C outlist_h('\ebSense Key:\en', key, ' : Equal comparison satisfied') CASE $D outlist_h('\ebSense Key:\en', key, ' : Volume Overflow') CASE $E outlist_h('\ebSense Key:\en', key, ' : Miscompare') DEFAULT outlist_h('\ebSense Key:\en', key, ' : Reserved Sense Key') ENDSELECT IF reply.sensecode > NIL outlist_h('\ebSense Code:\en', reply.sensecode, NIL) outlist_h('\ebSense Code Qualifier:\en', reply.sensequal, NIL) ENDIF ENDPROC /* ** This procedure handles the data returned from a mode sense request ** (ie Device Parameters). It is quite complex because the data is in the form ** of many pages which have to be processed. In addition to that, a page type ** may have to be processed differently, or have a different meaning depending ** on the type of device queried. */ PROC process_modesense(reply:PTR TO m_sense) DEF page:PTR TO CHAR, pagetype ->outlist_i('\ebMode Data Length:\en', reply.datalen, ' bytes') IF reply.medium = 0 THEN outlist('\ebInserted Medium Type:\en', 'Default') ELSE outlist_i('\ebInserted Medium Type:\en', reply.medium, ' (See supported media page)') ->outlist_i('\ebDescriptor Length:\en', reply.desclen, ' bytes') IF reply.desclen = 8 outlist_i('\ebLogical Blocks:\en', (reply.blocks AND M_LBLOCKS), NIL) outlist_i('\ebLogical Block Length:\en', (reply.blocklen AND M_LBLOCKS), ' bytes') page:=(reply + SIZEOF m_sense) WHILE page < (reply + reply.datalen) pagetype:=(Char(page) AND M_PAGETYPE) outlist(' ', ' ') SELECT pagetype CASE $1 SELECT $A OF global_devtype CASE DEV_DIRECT outlist('\ebInformation Page:\en', 'Error Recovery Parameters') ->outlist_i('\ebPage Length:\en', Char(page+1), ' bytes') outlist_i('\ebRetries on Read Error:\en', Char(page+3), NIL) outlist_i('\ebRetries on Write Error:\en', Char(page+8), NIL) outlist_i('\ebCorrection Span:\en', Char(page+4), NIL) outlist_i('\ebHead Offset Count:\en', Char(page+5), NIL) outlist_i('\ebData Strobe Offset Count:\en', Char(page+6), NIL) CASE DEV_SEQUENTIAL outlist('\ebInformation Page:\en', 'Error Recovery Parameters') ->outlist_i('\ebPage Length:\en', Char(page+1), NIL) outlist_i('\ebRetries on Read Error:\en', Char(page+3), NIL) outlist_i('\ebRetries on Write Error:\en', Char(page+8), NIL) CASE DEV_CDROM outlist('\ebInformation Page:\en', 'Error Recovery Parameters') ->outlist_i('\ebPage Length:\en', Char(page+1), NIL) outlist_i('\ebRetries on Read Error:\en', Char(page+3), NIL) ENDSELECT CASE $2 outlist('\ebInformation Page:\en', 'Disconnection and Reconnection Parameters') ->outlist_i('\ebPage Length:\en', Char(page+1), ' bytes') outlist_i('\ebBuffer Full Ratio:\en', Char(page+2), NIL) outlist_i('\ebBuffer Empty Ratio:\en', Char(page+3), NIL) outlist_i('\ebBus Inactivity Limit:\en', Int(page+4), NIL) outlist_i('\ebDisconnect Time Limit:\en', Int(page+6), NIL) outlist_i('\ebConnect Time Limit:\en', Int(page+8), NIL) outlist_i('\ebMaximum Burst Size:\en', Int(page+10), NIL) CASE $3 IF global_devtype=DEV_DIRECT outlist('\ebInformation Page:\en', 'Formatting Parameters') ->outlist_i('\ebPage Length:\en', Char(page+1), ' bytes') outlist_i('\ebTracks Per Zone:\en', Int(page+2), NIL) outlist_i('\ebAlt. Sectors Per Zone:\en', Int(page+4), NIL) outlist_i('\ebAlt. Tracks Per Zone:\en', Int(page+6), NIL) outlist_i('\ebAlt. Tracks Per Logical Unit:\en', Int(page+8), NIL) outlist_i('\ebSectors Per Track:\en', Int(page+10), NIL) outlist_i('\ebBytes Per Physical Sector:\en', Int(page+12), NIL) outlist_i('\ebInterleave:\en', Int(page+14), NIL) outlist_i('\ebTrack Skew Factor:\en', Int(page+16), NIL) outlist_i('\ebCylinder Skew Factor:\en', Int(page+18), NIL) ENDIF CASE $4 IF global_devtype=DEV_DIRECT outlist('\ebInformation Page:\en', 'Rigid Disk Geometry Parameters') ->outlist_i('\ebPage Length:\en', Char(page+1), ' bytes') outlist_i('\ebCylinders:\en', Int(page+2), NIL) outlist_i('\ebHeads:\en', Char(page+5), NIL) IF Int(page+12) = 0 THEN outlist('\ebStep Rate\en:', 'Device Default') ELSE outlist_i('\ebStep Rate:\en', Int(page+12)*100, ' ns') outlist_i('\ebLanding Cylinder:\en', Int(page+14), NIL) outlist_i('\ebRotation Rate:', Int(page+20), ' rpm') ENDIF CASE $5 IF global_devtype=DEV_DIRECT outlist('\ebInformation Page:\en', 'Flexible Disk Geometry Parameters') ->outlist_i('\ebPage Length:\en', Char(page+1), ' bytes') outlist_i('\ebTransfer Rate\en', (Int(page+2)/8), ' K/sec') outlist_i('\ebHeads\en:', Char(page+4), NIL) outlist_i('\ebSecters Per Track:\en', Char(page+5), NIL) outlist_i('\ebBytes Per Sector:\en', Int(page+6), NIL) outlist_i('\ebCylinders:\en', Int(page+8), NIL) IF Int(page+14) = 0 THEN outlist('\ebStep Rate\en:', 'Device Default') ELSE outlist_i('\ebStep Rate:\en', Int(page+14)*100, ' us') outlist_i('\ebRotation Rate:\en', Int(page+28), ' rpm') ENDIF CASE $7 SELECT $A OF global_devtype CASE DEV_DIRECT outlist('\ebInformation Page:\en', 'Verify Error Recovery Parameters') ->outlist_i('\ebPage Length:\en', Char(page+1), ' bytes') outlist_i('\ebVerify Retries:\en', Char(page+3), NIL) outlist_i('\ebVerify Correction Span:\en', Char(page+4), NIL) CASE DEV_CDROM outlist('\ebInformation Page:\en', 'Verify Error Recovery Parameters') ->outlist_i('\ebPage Length:\en', Char(page+1), ' bytes') outlist_h('\ebError Recovery Parameter:\en', Char(page+2), NIL) outlist_i('\ebVerify Retries:\en', Char(page+3), NIL) ENDSELECT CASE $8 SELECT $A OF global_devtype CASE DEV_DIRECT, DEV_CDROM, DEV_OPTICAL outlist('\ebInformation Page:\en', 'Cache Parameters') ->outlist_i('\ebPage Length:\en', Char(page+1), ' bytes') IF (Char(page+2) AND M_READCACHE) = 0 THEN outlist('\ebRead Cache:\en', 'Enabled') ELSE outlist('\ebRead Cache:\en', 'Disabled or Unavailable') outlist_i('\ebMin Pre-Fetch:\en', Int(page+6), ' bytes') outlist_i('\ebMax Pre-Fetch:\en', Int(page+8), ' bytes') ENDSELECT CASE $9 outlist('\ebInformation Page:\en', 'Interface Mode') ->outlist_i('\ebPage Length:\en', Char(page+1), ' bytes') IF (Int(page+2)) = 0 outlist('\ebInterface ID:\en', 'Small Computer Systems Interface (SCSI)') ELSEIF (Int(page+2))=1 outlist('\ebInterface ID:\en', 'Storage Module Interface (SMI)') ELSEIF (Int(page+2))=2 outlist('\ebInterface ID:\en', 'Enhanced Small Device Interface (ESDI)') ELSEIF (Int(page+2))=3 outlist('\ebInterface ID:\en', 'Intelligent Peripheral Interface 2 (IPI-2)') ELSEIF (Int(page+2))=4 outlist('\ebInterface ID:\en', 'Intelligent Peripheral Interface 3 (IPI-3)') ELSE outlist('\ebInterface ID:\en', 'Vendor Specific') ENDIF CASE $A outlist('\ebInformation Page:\en', 'Control Mode') ->outlist_i('\ebPage Length:\en', Char(page+1), ' bytes') IF (Char(page+3) AND M_QALGORITHM)=16 outlist('\ebQueuing Algorithm:\en', 'Unrestricted reordering allowed') ELSEIF (Char(page+3) AND M_QALGORITHM)=0 outlist('\ebQueuing Algorithm:\en', 'Restricted reordering') ELSE outlist('\ebQueuing Algorithm:\en', 'Vendor Specific') ENDIF IF (Char(page+3) AND M_QUEUING)=1 outlist('\ebQueuing:', 'Disabled') ELSE outlist('\ebQueuing:', 'Enabled') ENDIF CASE $B SELECT $A OF global_devtype CASE DEV_DIRECT outlist('\ebInformation Page:\en', 'Supported Media') ->outlist_i('\ebPage Length:\en', Char(page+1), ' bytes') outlist_i('\ebMedium Type 1:\en', Char(page+4), NIL) outlist_i('\ebMedium Type 2:\en', Char(page+5), NIL) outlist_i('\ebMedium Type 3:\en', Char(page+6), NIL) outlist_i('\ebMedium Type 4:\en', Char(page+7), NIL) CASE DEV_CDROM outlist('\ebInformation Page:\en', 'Supported Media') ->outlist_i('\ebPage Length:\en', Char(page+1), ' bytes') IF Char(page+4) = NIL outlist('\ebMedium Type 1:\en', 'Only the Default medium') ELSEIF Char(page+4) = 1 outlist('\ebMedium Type 1:\en', '120mm Data CD-ROM') ELSEIF Char(page+4) = 2 outlist('\ebMedium Type 1:\en', '120mm Audio CD-ROM') ELSEIF Char(page+4) = 3 outlist('\ebMedium Type 1:\en', '120mm Mixed Data & Audio') ELSEIF Char(page+4) = 5 outlist('\ebMedium Type 1:\en', '80mm Data CD-ROM') ELSEIF Char(page+4) = 6 outlist('\ebMedium Type 1:\en', '80mm Audio CD-ROM') ELSEIF Char(page+4) = 7 outlist('\ebMedium Type 1:\en', '80mm Mixed Data & Audio') ELSE outlist('\ebMedium Type 1:\en', 'Vendor Specific') ENDIF IF Char(page+5) = NIL outlist('\ebMedium Type 2:\en', 'Only the Default medium') ELSEIF Char(page+5) = 1 outlist('\ebMedium Type 2:\en', '120mm Data CD-ROM') ELSEIF Char(page+5) = 2 outlist('\ebMedium Type 2:\en', '120mm Audio CD-ROM') ELSEIF Char(page+5) = 3 outlist('\ebMedium Type 2:\en', '120mm Mixed Data & Audio') ELSEIF Char(page+5) = 5 outlist('\ebMedium Type 2:\en', '80mm Data CD-ROM') ELSEIF Char(page+5) = 6 outlist('\ebMedium Type 2:\en', '80mm Audio CD-ROM') ELSEIF Char(page+5) = 7 outlist('\ebMedium Type 2:\en', '80mm Mixed Data & Audio') ELSE outlist('\ebMedium Type 2:\en', 'Vendor Specific') ENDIF IF Char(page+6) = NIL outlist('\ebMedium Type 3:\en', 'Only the Default medium') ELSEIF Char(page+6) = 1 outlist('\ebMedium Type 3:\en', '120mm Data CD-ROM') ELSEIF Char(page+6) = 2 outlist('\ebMedium Type 3:\en', '120mm Audio CD-ROM') ELSEIF Char(page+6) = 3 outlist('\ebMedium Type 3:\en', '120mm Mixed Data & Audio') ELSEIF Char(page+6) = 5 outlist('\ebMedium Type 3:\en', '80mm Data CD-ROM') ELSEIF Char(page+6) = 6 outlist('\ebMedium Type 3:\en', '80mm Audio CD-ROM') ELSEIF Char(page+6) = 7 outlist('\ebMedium Type 3:\en', '80mm Mixed Data & Audio') ELSE outlist('\ebMedium Type 3:\en', 'Vendor Specific') ENDIF IF Char(page+7) = NIL outlist('\ebMedium Type 4:\en', 'Only the Default medium') ELSEIF Char(page+7) = 1 outlist('\ebMedium Type 4:\en', '120mm Data CD-ROM') ELSEIF Char(page+7) = 2 outlist('\ebMedium Type 4:\en', '120mm Audio CD-ROM') ELSEIF Char(page+7) = 3 outlist('\ebMedium Type 4:\en', '120mm Mixed Data & Audio') ELSEIF Char(page+7) = 5 outlist('\ebMedium Type 4:\en', '80mm Data CD-ROM') ELSEIF Char(page+7) = 6 outlist('\ebMedium Type 4:\en', '80mm Audio CD-ROM') ELSEIF Char(page+7) = 7 outlist('\ebMedium Type 4:\en', '80mm Mixed Data & Audio') ELSE outlist('\ebMedium Type 4:\en', 'Vendor Specific') ENDIF ENDSELECT CASE $C IF global_devtype=DEV_DIRECT outlist('\ebInformation Page:\en', 'Notch Parameters') ->outlist_i('\ebPage Length:\en', Char(page+1), ' bytes') outlist_i('\ebMax Notches:\en', Int(page+4), NIL) outlist_i('\ebActive Notch:\en', Int(page+6), NIL) ENDIF CASE $D IF global_devtype=DEV_CDROM outlist('\ebInformation Page:\en', 'CD-ROM Parameters') ->outlist_i('\ebPage Length:\en', Char(page+1), ' bytes') outlist_h('\ebInactivity Multiplier:\en', (Char(page+3) AND M_INAC_MPLIER), NIL) outlist_i('\ebS Units per MSF:\en', Int(page+4), NIL) outlist_i('\ebF Units per MSF:\en', Int(page+6), NIL) ENDIF CASE $E IF global_devtype=DEV_CDROM outlist('\ebInformation Page:\en', 'CD-ROM Audio Parameters') ->outlist_i('\ebPage Length:\en', Char(page+1), ' bytes') outlist_i('\ebPort 0 Volume Level:\en', Char(page+9), NIL) outlist_i('\ebPort 1 Volume Level:\en', Char(page+11), NIL) outlist_i('\ebPort 2 Volume Level:\en', Char(page+13), NIL) outlist_i('\ebPort 3 Volume Level:\en', Char(page+15), NIL) ENDIF CASE $10 IF global_devtype=DEV_SEQUENTIAL outlist('\ebInformation Page:\en', 'Sequential Device Configuration') ->outlist_i('\ebPage Length:\en', Char(page+1), ' bytes') outlist_i('\ebActive Recording Format:\en', (Char(page+2) AND M_RECFORMAT), ' (All values are vendor specific)') outlist_i('\ebActive Logical Partition:\en', Char(page+3), NIL) outlist_i('\ebWrite Buffer Ratio:\en', Char(page+4), NIL) outlist_i('\ebRead Buffer Ratio:\en', Char(page+5), NIL) outlist_i('\ebWrite Delay:\en', Int(page+6)*100, ' ms') IF Char(page+9) = 0 THEN outlist('\ebGap Size:\en', 'Device Default') ELSE outlist_i('\ebGap Size:\en', Char(page+9), NIL) IF Char(page+14) = 0 outlist('\ebCompression:\en', 'Unavailable or disabled') ELSEIF Char(page+14) = 1 outlist('\ebCompression:\en', 'Enabled') ENDIF ENDIF ENDSELECT ->outlist_i('\ebInformation Page:\en', pagetype , NIL) page:=(page + Char(page+1) +2) ENDWHILE ENDIF ENDPROC PROC process_log_support(reply:PTR TO l_sense) DEF x=0 ->outlist_i('\ebLog Size:\en', reply.len, ' bytes') outlist(' ', ' ') FOR x:=0 TO (reply.len-1) SELECT $3F OF Char(reply+x+4) CASE $0 ->No real point in listing it, we know the disk supports it or we wouldn't get a reply ->outlist_h('\ebFound Log:\en', Char(reply+x+4), ': List of supported log types') CASE $1 outlist_h('\ebFound Log:\en', Char(reply+x+4), ': Buffer Over-run and Under-run Log') CASE $2 outlist_h('\ebFound Log:\en', Char(reply+x+4), ': Write Error Log') CASE $3 outlist_h('\ebFound Log:\en', Char(reply+x+4), ': Read Error Log') CASE $4 outlist_h('\ebFound Log:\en', Char(reply+x+4), ': Reverse-Read Error Log') CASE $5 outlist_h('\ebFound Log:\en', Char(reply+x+4), ': Verify Error Log') CASE $6 outlist_h('\ebFound Log:\en', Char(reply+x+4), ': Non-medium Error Log') CASE $7 outlist_h('\ebFound Log:\en', Char(reply+x+4), ': Last # of Error Event Log') DEFAULT outlist_h('\ebFound Log:\en', Char(reply+x+4), ': A Vendor Specific Log') ENDSELECT ENDFOR ENDPROC PROC process_log_errors(reply:PTR TO l_sense) DEF param:PTR TO l_param, plen=0, buildstr[100]:STRING ->outlist_i('\ebLog Size:\en', reply.len, ' bytes') param:=reply + (SIZEOF l_sense) outlist(' ', ' ') WHILE param < (reply + reply.len) SELECT $FF OF param.pcode2 CASE $0 StrCopy(buildstr, '\ebErrors Corrected w/o Delay:\en') CASE $1 StrCopy(buildstr, '\ebErrors Corrected w/ Delay:\en') CASE $2 StrCopy(buildstr, '\ebTotal Re-writes or Re-reads:\en') CASE $3 StrCopy(buildstr, '\ebTotal Errors Corrected:\en') CASE $4 StrCopy(buildstr, '\ebTimes Correction Algorithm Used:\en') CASE $5 StrCopy(buildstr, '\ebTotal Bytes Processed:\en') CASE $6 StrCopy(buildstr, '\ebUncorrected Errors:\en') DEFAULT StrCopy(buildstr, '\ebVendor Parameter\en:') ENDSELECT -> This section is largely for programming diagnostics, not too useful -> for the end user /* outlist_i('\ebPCB:\en', param.pcb, NIL) outlist_i('\ebDU:\en', param.pcb AND %10000000, NIL) outlist_i('\ebDS:\en', param.pcb AND %01000000, NIL) outlist_i('\ebTSD:\en', param.pcb AND %00100000, NIL) outlist_i('\ebETC:\en', param.pcb AND %00010000, NIL) outlist_i('\ebTMC:\en', param.pcb AND %00001100, NIL) outlist_i('\ebReserved:\en', param.pcb AND %00000010, NIL) outlist_i('\ebLP:\en', param.pcb AND %00000001, NIL) outlist_i('\ebParameter Length:\en', param.len, NIL) */ plen:=param.len param:=param + (SIZEOF l_param) IF plen = 1 outlist_i(buildstr, Char(param), NIL) ELSEIF plen = 2 outlist_i(buildstr, Int(param), NIL) ELSEIF plen = 4 outlist_i(buildstr, Long(param), NIL) ELSEIF plen = 8 outlist_i(buildstr, Long(param), ' (First longword)') outlist_i(' ', Long(param+4), ' (Second longword)') ELSE outlist(buildstr, 'Cannot Decode') ENDIF param:=param + plen ENDWHILE ENDPROC PROC process_log_nmerrors(reply:PTR TO l_sense) DEF param:PTR TO l_param, plen=0, buildstr[100]:STRING ->outlist_i('\ebLog Size:\en', reply.len, ' bytes') param:=reply + (SIZEOF l_sense) outlist(' ', ' ') WHILE param < (reply + reply.len) SELECT $FF OF param.pcode2 CASE $0 StrCopy(buildstr, '\ebNon-Medium Error Count:\en') DEFAULT StrCopy(buildstr, '\ebVendor Parameter:\en') ENDSELECT /* outlist_i('\ebPCB:\en', param.pcb, NIL) outlist_i('\ebDU:\en', param.pcb AND %10000000, NIL) outlist_i('\ebDS:\en', param.pcb AND %01000000, NIL) outlist_i('\ebTSD:\en', param.pcb AND %00100000, NIL) outlist_i('\ebETC:\en', param.pcb AND %00010000, NIL) outlist_i('\ebTMC:\en', param.pcb AND %00001100, NIL) outlist_i('\ebReserved:\en', param.pcb AND %00000010, NIL) outlist_i('\ebLP:\en', param.pcb AND %00000001, NIL) outlist_i('\ebParameter Length:\en', param.len, NIL) */ plen:=param.len param:=param + (SIZEOF l_param) IF plen = 1 outlist_i(buildstr, Char(param), NIL) ELSEIF plen = 2 outlist_i(buildstr, Int(param), NIL) ELSEIF plen = 4 outlist_i(buildstr, Long(param), NIL) ELSEIF plen = 8 outlist_i(buildstr, Long(param), ' (Lower longword)') outlist_i(' ', Long(param+4), ' (Upper longword)') ELSE outlist(buildstr, 'Cannot Decode') ENDIF param:=param + plen ENDWHILE ENDPROC PROC process_log_buffer(reply:PTR TO l_sense) DEF param:PTR TO lb_param ->outlist_i('\ebLog Size:\en', reply.len, ' bytes') outlist(' ', ' ') param:=reply + SIZEOF l_sense /* WHILE param < (reply + reply.len) ENDWHILE */ ENDPROC PROC process_log_events(reply:PTR TO l_sense) outlist_i('\ebLog Size:\en', reply.len, ' bytes') outlist(' ', ' ') ENDPROC /* ** Adds entries into the listview where both parameters are strings. The first ** string is column one, the second is column two. */ PROC outlist(str:PTR TO CHAR, str2:PTR TO CHAR) DEF txt:listentry txt.field:=str txt.value:=str2 txt.driver:=NIL txt.unit:=NIL doMethodA(mui_output_lst, [MUIM_List_InsertSingle, txt, MUIV_List_Insert_Bottom]) ENDPROC /* ** Adds entries into the listview where the first parameter is a string, the ** second is an integer, and the third is an optional string. The first string ** is column one, the integer is converted into a string and is column two. ** In the case of the last string (if present) this is appended in column two ** and is usually used for display a value type (eg bytes) */ PROC outlist_i(str:PTR TO CHAR, int, valtype:PTR TO CHAR) DEF txt:listentry, str2[80]:STRING IF valtype=NIL THEN StringF(str2, '\d', int) ELSE StringF(str2, '\d\s', int, valtype) txt.field:=str txt.value:=str2 txt.driver:=NIL txt.unit:=NIL doMethodA(mui_output_lst, [MUIM_List_InsertSingle, txt, MUIV_List_Insert_Bottom]) ENDPROC /* ** Almost identical to outlist_i, except the integer is converted into Hex ** before being made into a string */ PROC outlist_h(str:PTR TO CHAR, int, valtype:PTR TO CHAR) DEF txt:listentry, str2[80]:STRING IF valtype=NIL THEN StringF(str2, '$\h', int) ELSE StringF(str2, '$\h\s', int, valtype) txt.field:=str txt.value:=str2 txt.driver:=NIL txt.unit:=NIL doMethodA(mui_output_lst, [MUIM_List_InsertSingle, txt, MUIV_List_Insert_Bottom]) ENDPROC /* ** This procedure adds special entries into the listview which the user may ** double click. They have a specific format, with additional information ** that is hidden from the display of the listview, but can be queried if ** a user double clicks an entry. */ PROC outlist_d(str:PTR TO CHAR, driver:PTR TO CHAR, unit) DEF txt:listentry, buildstr[99]:STRING StringF(buildstr, '\eb\s [\d]:\en', driver, unit) txt.field:=buildstr txt.value:=str txt.driver:=driver txt.unit:=unit doMethodA(mui_output_lst, [MUIM_List_InsertSingle, txt, MUIV_List_Insert_Bottom]) ENDPROC /* ** The display hook for the listview. Entries are processed from an object ** and insert into the appropriate columns */ PROC disp(hook:PTR TO LONG, array:PTR TO LONG, entry:PTR TO listentry) IF entry=NIL -> MUI means update the titles whenever entry=NIL array[0]:='\eb\eu\ecField\en' array[1]:='\eb\eu\ecValue\en' ELSE array[0]:=entry.field array[1]:=entry.value ENDIF ENDPROC 0 /* ** The construction hook for the listview. Memory needs to be reserved ** somewhere for each entry added, because only a pointer to a string actually ** gets inserted. This copies each string into memory reserved from a pool. The ** strings HAVE to be copied, as they will otherwise be freed by other ** procedures, meaning the pointers in the listview would suddenly be invalid. */ PROC construct (hook:PTR TO hook, pool:PTR TO LONG, obj:PTR TO listentry) DEF value, field, driver=NIL, new:PTR TO listentry IF (field:=AllocPooled(pool, StrLen(obj.field)+1)) THEN CopyMem(obj.field, field, StrLen(obj.field)+1) -> +1 ensures NULL byte is copied IF (value:=AllocPooled(pool, StrLen(obj.value)+1)) THEN CopyMem(obj.value, value, StrLen(obj.value)+1) -> ditto IF obj.driver<>NIL IF (driver:=AllocPooled(pool, StrLen(obj.driver)+1)) THEN CopyMem(obj.driver, driver, StrLen(obj.driver)+1) -> ditto ENDIF new:=AllocPooled(pool, SIZEOF listentry) new.field:=field new.value:=value new.driver:=driver new.unit:=obj.unit ENDPROC new /* ** Whenever an entry is removed from the listview, this procedure frees the ** previously reserved memory for the strings. */ PROC destruct (hook:PTR TO hook, pool:PTR TO LONG, obj:PTR TO listentry) FreePooled(pool, obj.field, StrLen(obj.field)+1) FreePooled(pool, obj.value, StrLen(obj.value)+1) IF obj.driver<>NIL THEN FreePooled(pool, obj.driver, StrLen(obj.driver)+1) FreePooled(pool, obj, SIZEOF listentry) ENDPROC /* ** Simple macro procedure for making MUI buttons. Parameter 1 is the button ** face, parameter 2 is the bubble help text. The buttons are automatically ** added to the cycle chain */ PROC make_button(face, bubble) DEF button button:=SimpleButton(face) SetAttrsA(button, [MUIA_ShortHelp, bubble, MUIA_CycleChain, 1, TAG_DONE]) ENDPROC button /* ** Simple macro procedure for making cycle lists. Parameter 1 is an array of ** the cycle contents, parameter 2 is the key which cycles it and parameter 3 ** is the bubble help test. */ PROC make_keycycle(face, key, bubble) DEF cycle cycle:=KeyCycle(face, key) SetAttrsA(cycle, [MUIA_ShortHelp, bubble, MUIA_CycleChain, 1, TAG_DONE]) ENDPROC cycle /* ** This procedure is called when the user double clicks and entry in the ** listview. It queries the hidden data (as handled by outlist_d()) to ** discover which device and unit to send the inquiry command to. */ PROC click_inquiry() DEF entry:PTR TO listentry, driver[99]:STRING, unit[4]:STRING doMethodA(mui_output_lst, [MUIM_List_GetEntry, MUIV_List_GetEntry_Active, {entry}]) IF entry.driver <> NIL StrCopy(driver, entry.driver) StringF(unit, '\d', entry.unit) set(mui_device_tb, MUIA_String_Contents, driver) set(mui_unit_tb, MUIA_String_Contents, unit) doMethodA(mui_output_lst, [MUIM_List_Clear]) query(driver, Val(unit), [SCSI_INQUIRY, 0, 0, 0, 36, 0]:cdb6, SIZEOF cdb6)=0 ENDIF ENDPROC /* ** Procedure to fill an array with device drivers from the execlist. The array ** is used in the device driver poplist so the user can select one instead of ** manually typing it. */ PROC grab_devices() DEF i=0, devnode:PTR TO ln, devlist:PTR TO lh, d[99]:STRING -> NOTE. This might need placing inside a Forbid()/Permit() pair but -> I'm not entirely certain about that. execobject:=execbase devlist:=execobject.devicelist devnode:=devlist.head WHILE devnode.succ StrCopy(d, devnode.name) IF StrCmp(d, 'audio.device')=TRUE -> We only filter out ELSEIF StrCmp(d, 'audio.device')=TRUE -> standard AmigaOS ELSEIF StrCmp(d, 'timer.device')=TRUE -> drivers which are not ELSEIF StrCmp(d, 'gameport.device')=TRUE -> appropriate because ELSEIF StrCmp(d, 'keyboard.device')=TRUE -> filtering a large ELSEIF StrCmp(d, 'console.device')=TRUE -> amount of drivers ELSEIF StrCmp(d, 'clipboard.device')=TRUE -> would be expensive ELSEIF StrCmp(d, 'ramdrive.device')=TRUE -> on slow CPUs. ELSEIF StrCmp(d, 'input.device')=TRUE ELSEIF StrCmp(d, 'trackdisk.device')=TRUE ELSEIF StrCmp(d, 'serial.device')=TRUE ELSEIF StrCmp(d, 'printer.device')=TRUE ELSEIF StrCmp(d, 'parallel.device')=TRUE ELSE devicelist[i]:=devnode.name i++ ENDIF devnode:=devnode.succ ENDWHILE devicelist[i]:=NIL ENDPROC